using Web.Domain.Entity;
using Web.Application.Utils;
using Web.Application.ResDto;
using Web.Application.ReqDto.ServerDto;
using Web.Application.Common.Interface;
using Web.Application.Common.Interface.IServer;
using Web.Application.ReqDto;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using Newtonsoft.Json;

namespace Web.Services.Services
{
    public class CurriCulumServices : ICurriCulumServices
    {
        // 依赖注入
        private readonly IRepository<CurriCulum> _curriCulum;
        public CurriCulumServices(IRepository<CurriCulum> curriCulum)
        {
            _curriCulum = curriCulum;
        }

        /*初始容量*/
        public static int initialCapacity = 7;
        /*并发级别*/
        public static int concurrencyLevel = Environment.ProcessorCount * 2;

        // 构造 ConcurrentDictionary<TKey,TValue> 对象
        public ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>(concurrencyLevel, initialCapacity);

        // 初始化 ConcurrentDictionary<TKey,TValue> 的键
        int addCCKey = -1;

        // 添加方法 异步
        // 传入：指定类型的 Dto (数据传输对象)
        // 返回：string
        // data：添加完成后的数据
        // 成功返回 200
        // 传入格式错误的数据或传入为空的数据返回 400
        // 失败返回 405
        public async Task<string> AddCurriCulum(CurriCulumDTO curriCulumDTO)
        {
            if (curriCulumDTO.CurriCulumData != "" && curriCulumDTO.SpecializedName != "" && curriCulumDTO.CurriCulumData != null && curriCulumDTO.SpecializedName != null)
            {
                // cd.TryAdd(addCCKey, curriCulumDTO.CurriCulumData);
                // 添加
                var AddTask = await Task.WhenAll(Task.Run(async () =>
                                    {
                                        // var (CcDTOData, threadId) = (cd[addCCKey], Thread.CurrentThread.ManagedThreadId);
                                        addCCKey++;
                                        // cd.TryAdd(addCCKey, curriCulumDTO.CurriCulumData);
                                        if (cd.TryAdd(addCCKey, curriCulumDTO.CurriCulumData))
                                        {
                                            // Console.WriteLine($"线程 {threadId}，添加 键：{addCCKey}、值：{curriCulumDTO.CurriCulumData} 成功！");

                                            // 构造 CurriCulum 实体类型的对象，并对其属性进行赋值，然后对 CurriCulum 表进行添加数据操作
                                            CurriCulum entity = new CurriCulum();

                                            entity.CurriCulumData = cd[addCCKey];
                                            entity.SpecializedName = curriCulumDTO.SpecializedName;

                                            await _curriCulum.AddAsync(entity);

                                            var res = new
                                            {
                                                code = 200,
                                                data = entity,
                                                msg = "添加成功！"
                                            };

                                            return res.SerializeObject();
                                        }
                                        else
                                        {
                                            // Console.WriteLine($"线程 {threadId}，添加 键：{addCCKey}、值：{curriCulumDTO.CurriCulumData} 失败！");
                                            // cd.TryAdd失败情况：（这与并发无关）

                                            // 1. ArgumentNullException - 当键为空时引用
                                            // 2. 溢出异常 - 当达到最大元素数时
                                            // 3. 它返回 假 如果已存在具有相同键的元素

                                            // 两个线程同时插入一个项目，那么可能会发生以下情况:
                                            // 如果键不同，两个插入都可以正常工作。
                                            // 一个插入工作正常并返回 true，另一个插入失败(无一异常(exception))并返回 false。
                                            // 如果两个线程尝试插入具有相同键的项目并且基本上只有一个会赢而另一个会输，则会发生这种情况。

                                            var res = new
                                            {
                                                code = 405,
                                                data = "",
                                                msg = "此处课程已被添加！添加失败！"
                                            };

                                            return res.SerializeObject();
                                        }
                                    }));

                if (AddTask.Length > 0)
                {
                    var res = new
                    {
                        code = 405,
                        data = cd,
                        msg = "添加成功！......任务成功"
                    };

                    return res.SerializeObject();
                }
                else
                {
                    var res = new
                    {
                        code = 405,
                        data = "",
                        msg = "添加失败！......任务失败"
                    };

                    return res.SerializeObject();
                }
            }
            else
            {
                var res = new
                {
                    code = 400,
                    data = "",
                    msg = "输入课程或班级为空，添加失败！"
                };

                return res.SerializeObject();
            }
        }


        // 删除方法 异步
        // 传入：需要删除的意向的 主键ID
        // 返回：string
        // data：无
        // 成功返回 200
        // 失败返回 405
        public async Task<string> DeleteCurriCulum(Guid id)
        {
            var entity = await _curriCulum.GetByIdAsync(id);

            if (entity != null)
            {
                await _curriCulum.DeleteAsync(id);

                var res = new
                {
                    code = 200,
                    data = "",
                    msg = "删除成功！"
                };

                return res.SerializeObject();
            }
            else
            {
                var res = new
                {
                    code = 405,
                    data = "",
                    msg = "课程不存在，删除失败！"
                };

                return res.SerializeObject();
            }
        }


        // 查询排课列表
        // 传入：需要查询的排课列表的分页信息
        // 返回类型：string
        // 成功返回 200
        public string GetListOrByCurriCulumName(PageFromQuery query)
        {
            var entity = _curriCulum.Table.Where(x => x.IsDeleted == false).OrderBy(x => x.CreatedAt).ToList();

            if (entity != null)
            {
                var res = new
                {
                    code = 200,
                    data = entity,
                    msg = "获取数据成功！"
                };

                return res.SerializeObject();
            }
            else
            {
                var res = new
                {
                    code = 200,
                    data = entity,
                    msg = "数据列表为空，获取数据失败！"
                };

                return res.SerializeObject();
            }
        }


        // 修改方法 异步
        // 传入：需要修改的意向的 主键 ID 和修改内容
        // 返回：string
        // data：修改完成后的数据
        // 成功返回 200
        // 传入格式错误的数据或传入为空的数据返回 400
        // 失败返回 405
        public async Task<string> UpdatedCurriCulumName(Guid id, CurriCulumDTO curriCulumDTO)
        {
            var entity = await _curriCulum.GetByIdAsync(id);

            if (entity != null)
            {
                if (curriCulumDTO.CurriCulumData != "" && curriCulumDTO.SpecializedName != "" && curriCulumDTO.CurriCulumData != null && curriCulumDTO.SpecializedName != null)
                {
                    int cdKey = 0;

                    ConcurrentDictionary<string, string> dd = new ConcurrentDictionary<string, string>(concurrencyLevel, initialCapacity);
                    dd[curriCulumDTO.SpecializedName] = curriCulumDTO.CurriCulumData;

                    var UpdateTask = await Task.WhenAll(Task.Run(async () =>
                    {
                        entity.CurriCulumData = curriCulumDTO.CurriCulumData;
                        entity.SpecializedName = curriCulumDTO.SpecializedName;

                        if (cd.TryUpdate(cdKey, dd[curriCulumDTO.SpecializedName], curriCulumDTO.CurriCulumData))
                        {
                            await _curriCulum.UpdateAsync(entity);

                            var res = new
                            {
                                code = 200,
                                data = entity,
                                msg = "修改成功！"
                            };

                            return res.SerializeObject();
                        }
                        else
                        {
                            // Console.WriteLine($"修改键 {cdKey} 失败！");

                            var res = new
                            {
                                code = 405,
                                data = "",
                                msg = "目标课程不存在，修改失败！"
                            };

                            return res.SerializeObject();
                        }
                    }
                        ));
                    if (UpdateTask.Length > 0)
                    {
                        var res = new
                        {
                            code = 405,
                            data = entity,
                            msg = "修改成功！......任务成功"
                        };

                        return res.SerializeObject();
                    }
                    else
                    {
                        var res = new
                        {
                            code = 405,
                            data = "",
                            msg = "修改失败！......任务失败"
                        };

                        return res.SerializeObject();
                    }
                }
                else
                {
                    var res = new
                    {
                        code = 400,
                        data = "",
                        msg = "未曾修改课程或未输入修改值！修改失败！"
                    };

                    return res.SerializeObject();
                }
            }
            else
            {
                var res = new
                {
                    code = 405,
                    data = "",
                    msg = "课程不存在，修改失败！"
                };

                return res.SerializeObject();
            }
        }

        // 查询排课列表（模糊查询）
        // 传入：需要查询的排课列表的班级信息
        // 返回类型：string
        // 成功返回 200
        // 失败返回 405
        public async Task<string> GetCurriCulumNameBySpecializedName(string SpecializedName)
        {
            if (SpecializedName != "" && SpecializedName != null)
            {
                var entity = _curriCulum.Table.Where(x => x.SpecializedName.Contains(SpecializedName) && x.IsDeleted == false).OrderBy(x => x.CreatedAt).ToList();

                if (entity != null)
                {
                    var res = new
                    {
                        code = 200,
                        data = entity,
                        mag = "查询成功！"
                    };

                    return res.SerializeObject();
                }
                else
                {
                    var res = new
                    {
                        code = 405,
                        data = "",
                        mag = "课表不存在！查询失败！"
                    };

                    return res.SerializeObject();
                }
            }
            else
            {
                var entities = _curriCulum.Table.Where(x => x.IsDeleted == false).ToList();

                var res = new
                {
                    code = 200,
                    data = entities,
                    msg = "获取数据列表成功！"
                };

                return res.SerializeObject();
            }
        }
    }
}